package com.yanggu.scala.chapater18.covariantcontravariant

//协变、逆变、不变
//Scala的协变(+)，逆变(-)，协变covariant、逆变contravariant、不可变invariant
//对于一个带类型参数的类型，比如 List[T]，如果对A及其子类型B，满足 List[B]也符合List[A]的子类型，那么就称为covariance(协变)，如果 List[A]是 List[B]的子类型，即与原来的父子关系正相反，则称为contravariance(逆变)。如果一个类型支持协变或逆变，则称这个类型为variance(翻译为可变的或变型)，否则称为invariance(不可变的)
//在Java里，泛型类型都是invariant，比如 List<String> 并不是 List<Object> 的子类型。而scala支持，可以在定义类型时声明(用加号表示为协变，减号表示逆变)，如:traitList[+T]//在类型定义时声明为协变这样会把List[String]作为List[Any]的子类型。

//在这里引入关于这个符号的说明，在声明Scala的泛型类型时，“+”表示协变，而“-”表示逆变
//C[+T]：如果A是B的子类，那么C[A]是C[B]的子类，称为协变
//C[-T]：如果A是B的子类，那么C[B]是C[A]的子类，称为逆变
//C[T]：无论A和B是什么关系，C[A]和C[B]没有从属关系。称为不变.
object Demo01 {

  def main(args: Array[String]): Unit = {

    //不变
    val t1: Temp3[Sub] = new Temp3[Sub]("abc") //ok
    //    val t2: Temp3[Sub] = new Temp3[Super]("abc") //error
//    val t3: Temp3[Super] = new Temp3[Sub]("abc") //error
    val t4: Temp3[Sub] = new Temp3[Sub]("abc") //ok

    //协变
    val t5: Temp4[Super] = new Temp4[Sub]("abc") //ok
    val t6: Temp4[Sub] = new Temp4[Sub]("abc") //ok

    //逆变
    val t7: Temp5[Sub] = new Temp5[Sub]("abc") //ok
    val t8: Temp5[Sub] = new Temp5[Super]("abc") //ok
//    val t9: Temp5[Super] = new Temp5[Sub]("abc") //error

    test[String]("123")

  }

  def test[T](t: T) = {
    println(new Demo01[T].toString)
  }

}

class Demo01[T]

//协变
class Temp4[+A](title: String) {

  override def toString = title

}

//逆变
class Temp5[-A](title: String) {

  override def toString = title

}

//不变
class Temp3[A](title: String) {

  override def toString = title

}


class Super

class Sub extends Super
